package java_chapter;
/**
 * 第6章 类与对象 - 核心知识点演示
 *
 * 本文件演示了Java面向对象编程的基础概念：
 * 1. 类的基本概念和定义
 * 2. 定义类（属性、方法、构造器）
 * 3. 对象的创建与使用
 * 4. 参数传递（值传递 vs 引用传递）
 * 5. 匿名对象的使用
 *
 * 适合在IDEA中运行和学习
 */
public class ClassAndObjectDemo_chapter6 {

    public static void main(String[] args) {
        System.out.println("========== 第6章：类与对象 知识点演示 ==========\n");

        // 6.1 & 6.2 类的基本概念和定义类演示
        classBasicsDemo();

        // 6.4 对象的创建与使用演示
        objectCreationDemo();

        // 6.5 参数传递演示
        parameterPassingDemo();

        // 6.6 匿名对象演示
        anonymousObjectDemo();

        System.out.println("\n========== 演示结束 ==========");
    }

    /**
     * 6.1 & 6.2 类的基本概念和定义类演示
     *
     * 类（Class）是对象的模板，定义了对象的属性和行为
     * 对象（Object）是类的实例，具有具体的属性值
     */
    private static void classBasicsDemo() {
        System.out.println("1. 类的基本概念和定义演示：");

        // 创建学生对象，展示类和对象的关系
        Student student1 = new Student();  // 使用无参构造器
        Student student2 = new Student("张三", 20, "计算机科学");  // 使用有参构造器

        // 设置和获取对象属性
        student1.setName("李四");
        student1.setAge(19);
        student1.setMajor("软件工程");

        // 调用对象的方法
        student1.introduce();
        student2.introduce();

        System.out.println();
    }

    /**
     * 6.4 对象的创建与使用演示
     *
     * 对象创建的步骤：
     * 1. 声明对象引用
     * 2. 使用new关键字创建对象
     * 3. 调用构造器初始化对象
     */
    private static void objectCreationDemo() {
        System.out.println("2. 对象创建与使用演示：");

        // 步骤1：声明对象引用（此时对象还不存在）
        Calculator calc;

        // 步骤2：创建对象实例
        calc = new Calculator("科学计算器");

        // 步骤3：使用对象
        System.out.println("计算器名称：" + calc.getName());
        System.out.println("10 + 5 = " + calc.add(10, 5));
        System.out.println("10 - 5 = " + calc.subtract(10, 5));
        System.out.println("10 * 5 = " + calc.multiply(10, 5));
        System.out.println("10 / 5 = " + calc.divide(10, 5));

        // 一行代码创建和使用对象
        Calculator simpleCalc = new Calculator();
        System.out.println("简单计算：3 + 7 = " + simpleCalc.add(3, 7));

        System.out.println();
    }

    /**
     * 6.5 参数传递演示
     *
     * Java中的参数传递：
     * 1. 基本数据类型：值传递（传递的是值的副本）
     * 2. 引用数据类型：引用传递（传递的是对象的引用）
     */
    private static void parameterPassingDemo() {
        System.out.println("3. 参数传递演示：");

        // 基本数据类型的值传递演示
        int number = 10;
        System.out.println("调用方法前，number = " + number);
        changeNumber(number);  // 值传递，不会改变原变量
        System.out.println("调用方法后，number = " + number);  // 仍然是10

        // 引用数据类型的引用传递演示
        Student student = new Student("王五", 21, "数学");
        System.out.println("调用方法前：");
        student.introduce();

        changeStudent(student);  // 引用传递，会改变对象的状态
        System.out.println("调用方法后：");
        student.introduce();

        // 数组的引用传递演示
        int[] array = {1, 2, 3, 4, 5};
        System.out.println("调用方法前，数组：" + java.util.Arrays.toString(array));
        changeArray(array);  // 引用传递，会改变数组内容
        System.out.println("调用方法后，数组：" + java.util.Arrays.toString(array));

        System.out.println();
    }

    /**
     * 值传递示例：基本数据类型
     * 这个方法接收到的是number值的副本，修改不会影响原变量
     */
    private static void changeNumber(int num) {
        System.out.println("方法内部修改前，num = " + num);
        num = 100;  // 只是修改了副本，不影响原变量
        System.out.println("方法内部修改后，num = " + num);
    }

    /**
     * 引用传递示例：对象
     * 这个方法接收到的是对象的引用，可以通过引用修改对象的状态
     */
    private static void changeStudent(Student stu) {
        System.out.println("方法内部：正在修改学生信息...");
        stu.setName("赵六");  // 通过引用修改对象的属性
        stu.setAge(22);
        stu.setMajor("物理学");
    }

    /**
     * 引用传递示例：数组
     * 数组是引用类型，传递的是数组的引用
     */
    private static void changeArray(int[] arr) {
        System.out.println("方法内部：正在修改数组...");
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 10;  // 修改数组元素
        }
    }

    /**
     * 6.6 匿名对象演示
     *
     * 匿名对象：没有引用变量指向的对象
     * 特点：使用一次后就被垃圾回收，适合临时使用
     */
    private static void anonymousObjectDemo() {
        System.out.println("4. 匿名对象演示：");

        // 普通对象使用（有引用变量）
        Calculator namedCalc = new Calculator("普通计算器");
        System.out.println("普通对象计算：" + namedCalc.add(5, 3));

        // 匿名对象使用（没有引用变量）
        System.out.println("匿名对象计算：" + new Calculator("匿名计算器").add(5, 3));

        // 匿名对象作为方法参数
        processCalculator(new Calculator("参数计算器"));

        // 匿名对象链式调用（如果方法返回对象本身）
        System.out.println("学生信息处理结果：");
        new Student("匿名学生", 20, "匿名专业").introduce();

        // 注意：匿名对象使用完毕后立即成为垃圾，等待回收
        // 这行代码执行完后，创建的Calculator对象就没有引用指向它了
        new Calculator().add(1, 2);  // 计算结果没有被使用，对象立即成为垃圾

        System.out.println();
    }

    /**
     * 处理计算器对象的方法
     * 演示匿名对象作为参数传递
     */
    private static void processCalculator(Calculator calc) {
        System.out.println("处理计算器：" + calc.getName());
        System.out.println("测试计算：2 * 6 = " + calc.multiply(2, 6));
    }
}

/**
 * 学生类 - 演示类的定义
 *
 * 类的组成部分：
 * 1. 属性（成员变量）：描述对象的特征
 * 2. 方法（成员方法）：描述对象的行为
 * 3. 构造器：用于创建和初始化对象
 */
class Student {
    // 1. 属性定义（成员变量）
    private String name;    // 姓名 - 使用private封装
    private int age;        // 年龄
    private String major;   // 专业

    // 2. 构造器定义
    /**
     * 无参构造器
     * 当没有定义任何构造器时，Java会自动提供一个无参构造器
     * 一旦定义了有参构造器，就必须显式定义无参构造器（如果需要的话）
     */
    public Student() {
        // 可以设置默认值
        this.name = "未命名学生";
        this.age = 18;
        this.major = "未选择专业";
        System.out.println("调用了无参构造器，创建了默认学生对象");
    }

    /**
     * 有参构造器
     * 用于创建对象时直接初始化属性
     */
    public Student(String name, int age, String major) {
        this.name = name;    // this关键字区分成员变量和参数
        this.age = age;
        this.major = major;
        System.out.println("调用了有参构造器，创建了学生：" + name);
    }

    // 3. 方法定义
    /**
     * getter方法 - 获取私有属性的值
     * 这是封装的体现：通过公有方法访问私有属性
     */
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getMajor() {
        return major;
    }

    /**
     * setter方法 - 设置私有属性的值
     * 可以在setter中添加数据验证逻辑
     */
    public void setName(String name) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name;
        } else {
            System.out.println("姓名不能为空！");
        }
    }
    public void setAge(int age) {
        if (age >= 0 && age <= 150) {
            this.age = age;
        } else {
            System.out.println("年龄必须在0-150之间！");
        }
    }

    public void setMajor(String major) {
        this.major = major;
    }

    /**
     * 业务方法 - 学生自我介绍
     * 展示对象的行为
     */
    public void introduce() {
        System.out.println("大家好，我是" + name + "，今年" + age + "岁，专业是" + major);
    }

    /**
     * 业务方法 - 学习方法
     * 可以接收参数的方法
     */
    public void study(String subject) {
        System.out.println(name + "正在学习" + subject);
    }

    /**
     * 业务方法 - 计算年龄差
     * 可以接收同类型对象作为参数
     */
    public int getAgeDifference(Student other) {
        return Math.abs(this.age - other.age);
    }
}

/**
 * 计算器类 - 演示类的方法和对象使用
 *
 * 这个类展示了：
 * 1. 如何定义有意义的方法
 * 2. 方法的重载
 * 3. 对象状态的管理
 */
class Calculator {
    // 属性
    private String name;        // 计算器名称
    private int operationCount; // 操作次数统计

    // 构造器
    public Calculator() {
        this.name = "默认计算器";
        this.operationCount = 0;
    }

    public Calculator(String name) {
        this.name = name;
        this.operationCount = 0;
    }

    // getter方法
    public String getName() {
        return name;
    }

    public int getOperationCount() {
        return operationCount;
    }

    // 计算方法
    /**
     * 加法运算
     */
    public double add(double a, double b) {
        operationCount++;  // 统计操作次数
        return a + b;
    }

    /**
     * 减法运算
     */
    public double subtract(double a, double b) {
        operationCount++;
        return a - b;
    }

    /**
     * 乘法运算
     */
    public double multiply(double a, double b) {
        operationCount++;
        return a * b;
    }

    /**
     * 除法运算
     * 包含异常处理，展示方法中的逻辑处理
     */
    public double divide(double a, double b) {
        operationCount++;
        if (b == 0) {
            System.out.println("错误：除数不能为0！");
            return 0;
        }
        return a / b;
    }

    /**
     * 方法重载示例：计算多个数的和
     */
    public double add(double a, double b, double c) {
        operationCount++;
        return a + b + c;
    }
    /**
     * 方法重载示例：计算数组中所有数的和
     */
    public double add(double[] numbers) {
        operationCount++;
        double sum = 0;
        for (double num : numbers) {
            sum += num;
        }
        return sum;
    }

    /**
     * 重置计算器
     * 展示对象状态的管理
     */
    public void reset() {
        operationCount = 0;
        System.out.println(name + " 已重置，操作次数清零");
    }

    /**
     * 显示计算器信息
     */
    public void showInfo() {
        System.out.println("计算器：" + name + "，已执行操作：" + operationCount + "次");
    }
}

/**
 * 银行账户类 - 演示更复杂的类设计
 *
 * 这个类展示了：
 * 1. 数据封装和安全性
 * 2. 业务逻辑在方法中的实现
 * 3. 对象间的交互
 */
class BankAccount {
    // 私有属性，体现封装性
    private String accountNumber;  // 账户号码
    private String ownerName;      // 账户所有者
    private double balance;        // 账户余额
    private boolean isActive;      // 账户是否激活

    // 构造器
    public BankAccount(String accountNumber, String ownerName) {
        this.accountNumber = accountNumber;
        this.ownerName = ownerName;
        this.balance = 0.0;         // 初始余额为0
        this.isActive = true;       // 默认激活
        System.out.println("银行账户创建成功：" + accountNumber + "（" + ownerName + "）");
    }

    public BankAccount(String accountNumber, String ownerName, double initialBalance) {
        this(accountNumber, ownerName);  // 调用其他构造器
        if (initialBalance >= 0) {
            this.balance = initialBalance;
            System.out.println("初始存款：" + initialBalance + "元");
        }
    }

    public BankAccount(String 张三, double v) {
    }

    // getter方法
    public String getAccountNumber() {
        return accountNumber;
    }

    public String getOwnerName() {
        return ownerName;
    }

    public double getBalance() {
        return balance;
    }

    public boolean isActive() {
        return isActive;
    }

    /**
     * 存款方法
     * 展示业务逻辑和数据验证
     */
    public boolean deposit(double amount) {
        // 数据验证
        if (!isActive) {
            System.out.println("账户已冻结，无法存款");
            return false;
        }

        if (amount <= 0) {
            System.out.println("存款金额必须大于0");
            return false;
        }

        // 执行存款
        balance += amount;
        System.out.println("存款成功：+" + amount + "元，当前余额：" + balance + "元");
        return true;
    }

    /**
     * 取款方法
     */
    public boolean withdraw(double amount) {
        if (!isActive) {
            System.out.println("账户已冻结，无法取款");
            return false;
        }

        if (amount <= 0) {
            System.out.println("取款金额必须大于0");
            return false;
        }

        if (amount > balance) {
            System.out.println("余额不足，当前余额：" + balance + "元");
            return false;
        }

        balance -= amount;
        System.out.println("取款成功：-" + amount + "元，当前余额：" + balance + "元");
        return true;
    }

    /**
     * 转账方法 - 演示对象间的交互
     */
    public boolean transfer(BankAccount targetAccount, double amount) {
        if (!this.isActive || !targetAccount.isActive) {
            System.out.println("转账失败：账户已冻结");
            return false;
        }

        System.out.println("正在执行转账：" + this.ownerName + " → " + targetAccount.ownerName + "，金额：" + amount + "元");

        // 从当前账户取款
        if (this.withdraw(amount)) {
            // 向目标账户存款
            if (targetAccount.deposit(amount)) {
                System.out.println("转账成功完成");
                return true;
            } else {
                // 如果存款失败，需要回滚取款操作
                this.deposit(amount);
                System.out.println("转账失败：目标账户存款失败，已回滚");
                return false;
            }
        }

        return false;
    }

    /**
     * 冻结账户
     */
    public void freeze() {
        isActive = false;
        System.out.println("账户 " + accountNumber + " 已被冻结");
    }

    /**
     * 激活账户
     */
    public void activate() {
        isActive = true;
        System.out.println("账户 " + accountNumber + " 已激活");
    }

    /**
     * 显示账户信息
     */
    public void showAccountInfo() {
        System.out.println("=== 账户信息 ===");
        System.out.println("账户号码：" + accountNumber);
        System.out.println("所有者：" + ownerName);
        System.out.println("余额：" + balance + "元");
        System.out.println("状态：" + (isActive ? "正常" : "冻结"));
        System.out.println("===============");
    }
}

/**
 * 扩展演示类 - 展示类与对象的高级用法
 */
class AdvancedDemo {

    /**
     * 演示对象数组的使用
     */
    public static void demonstrateObjectArray() {
        System.out.println("5. 对象数组演示：");

        // 创建学生对象数组
        Student[] students = new Student[3];

        // 注意：此时数组中的元素都是null，需要分别创建对象
        students[0] = new Student("Alice", 20, "计算机科学");
        students[1] = new Student("Bob", 21, "数学");
        students[2] = new Student("Charlie", 19, "物理");

        // 遍历对象数组
        System.out.println("班级学生名单：");
        for (int i = 0; i < students.length; i++) {
            System.out.print((i + 1) + ". ");
            students[i].introduce();
        }

        // 使用增强for循环
        System.out.println("\n学生学习情况：");
        for (Student student : students) {
            student.study("Java编程");
        }

        System.out.println();
    }

    /**
     * 演示对象作为方法参数和返回值
     */
    public static void demonstrateObjectAsParameter() {
        System.out.println("6. 对象作为参数和返回值演示：");

        // 创建银行账户
        BankAccount account1 = new BankAccount("1001", "张三", 1000);
        BankAccount account2 = new BankAccount("1002", "李四", 500);

        // 对象作为参数传递
        processAccount(account1);

        // 对象之间的交互
        account1.transfer(account2, 200);

        // 显示最终状态
        account1.showAccountInfo();
        account2.showAccountInfo();

        System.out.println();
    }

    /**
     * 处理银行账户的辅助方法
     * 演示对象作为方法参数
     */
    private static void processAccount(BankAccount account) {
        System.out.println("正在处理账户：" + account.getOwnerName());
        account.deposit(100);
        account.withdraw(50);
    }

    /**
     * 演示this关键字的使用
     */
    public static void demonstrateThisKeyword() {
        System.out.println("7. this关键字演示：");

        // 创建演示对象
        ThisDemo demo = new ThisDemo("演示对象");
        demo.showThisUsage();

        System.out.println();
    }
}

/**
 * this关键字演示类
 */
class ThisDemo {
    private String name;

    public ThisDemo(String name) {
        this.name = name;  // this.name指的是成员变量，name指的是参数
    }

    public void showThisUsage() {
        System.out.println("对象名称：" + this.name);

        // this可以调用其他方法
        this.anotherMethod();

        // this可以作为参数传递（传递当前对象的引用）
        processThisObject(this);
    }

    private void anotherMethod() {
        System.out.println("this调用的其他方法");
    }

    private void processThisObject(ThisDemo obj) {
        System.out.println("接收到的对象：" + obj.name);
        System.out.println("this == obj: " + (this == obj));  // 比较引用是否相同
    }
}

/**
 * 主测试类的扩展 - 添加更多演示
 */
class ExtendedClassAndObjectDemo {

    public static void runAdvancedDemos() {
        System.out.println("\n========== 高级演示开始 ==========");

        // 对象数组演示
        AdvancedDemo.demonstrateObjectArray();

        // 对象作为参数演示
        AdvancedDemo.demonstrateObjectAsParameter();

        // this关键字演示
        AdvancedDemo.demonstrateThisKeyword();

        // 对象生命周期演示
        demonstrateObjectLifecycle();

        System.out.println("========== 高级演示结束 ==========");
    }

    /**
     * 演示对象的生命周期
     */
    private static void demonstrateObjectLifecycle() {
        System.out.println("8. 对象生命周期演示：");

        {
            // 在代码块中创建对象
            Student tempStudent = new Student("临时学生", 18, "临时专业");
            System.out.println("在代码块中创建了临时学生对象");
            tempStudent.introduce();
        } // 代码块结束，tempStudent引用消失，对象成为垃圾回收的候选

        // 创建大量对象演示垃圾回收
        System.out.println("创建大量临时对象...");
        for (int i = 0; i < 5; i++) {
            // 每次循环创建的匿名对象在使用后立即成为垃圾
            new Calculator("临时计算器" + i).add(i, i + 1);
        }

        // 建议垃圾回收（不保证立即执行）
        System.gc();
        System.out.println("已建议进行垃圾回收");

        System.out.println();
    }

    /**
     * 主方法 - 运行所有演示
     */
    public static void main(String[] args) {
        // 运行基础演示
        ClassAndObjectDemo_chapter6.main(args);

        // 运行高级演示
        runAdvancedDemos();

        // 总结
        System.out.println("\n========== 学习总结 ==========");
        System.out.println("通过以上演示，你应该掌握了：");
        System.out.println("1. 类的定义：属性、方法、构造器");
        System.out.println("2. 对象的创建、使用和生命周期");
        System.out.println("3. 封装性：private属性 + public方法");
        System.out.println("4. 参数传递：值传递 vs 引用传递");
        System.out.println("5. 匿名对象的特点和使用场景");
        System.out.println("6. this关键字的使用");
        System.out.println("7. 对象数组和对象间的交互");
        System.out.println("================================");
    }
}